const {getCurrentUrl, downFile,clearAll} = require("./common");
const proj4 = require('proj4');
const EXTENDS_3857 = 20037508.3427892;
const mapUrl1="http://a.tile.osm.org/{z}/{x}/{y}.png";
const mapUrl2="http://b.tile.osm.org/{z}/{x}/{y}.png";
const mapUrl3="http://c.tile.osm.org/{z}/{x}/{y}.png";
let levelMin=1;
let levelMax=17;
const latMax=85;
const latMin=-85;
const lonMax=180;
const lonMin=-180;
// const latMax=49.27;
// const latMin=25.09;
// const lonMax=-67.32;
// const lonMin=-126.04;
const rootPath="/mylvm/osm/";
let addModel=false;
init();


function init() {
  let arguments = process.argv.splice(2);
  console.log(arguments);
  if(arguments.indexOf("--add")>-1){
    addModel=true;
    console.log("新增模式");
  }
  if(arguments.indexOf("-levelMin")>-1){
    levelMin=Number(arguments[arguments.indexOf("-levelMin")+1]);
    console.log("最小等级"+levelMin);
  }
  if(arguments.indexOf("-levelMax")>-1){
    levelMax=Number(arguments[arguments.indexOf("-levelMax")+1]);
    console.log("最大等级"+levelMax);
  }
  if(arguments.indexOf("-level")>-1){
    levelMin=Number(arguments[arguments.indexOf("-level")+1]);
    levelMax=levelMin;
  }
  startDown().then(()=>{
    console.log("下载完成")
  }).catch(err=>{
    console.log(err);
    console.log("下载失败已停止")
  });
}


async function startDown() {
  let point1 = Wgs84ToMector(latMax, lonMax);
  let point2 = Wgs84ToMector(latMin, lonMin);
  // let point1 = [EXTENDS_3857,EXTENDS_3857];
  // let point2 = [-EXTENDS_3857,-EXTENDS_3857];
  for (let i = levelMin; i <= levelMax; i++) {
    console.log( "正在下载第"+i+"级");
    await getTMSCoord(point2[0],point2[1],point1[0], point1[1], i);
  }
}

async function getTMSCoord(xMin, yMin, xMax, yMax, level) {

  let tile_size = EXTENDS_3857 / Math.pow(2, level - 1);//当前等级瓦片坐标宽度（宽高相等）
  let x1 = Math.ceil((xMin + EXTENDS_3857) / tile_size) - 1;//起始X,减1是因为从0开始
  let x2 = Math.ceil((xMax + EXTENDS_3857) / tile_size) - 1;//终止X
  //谷歌地图TMSy值计算
   let   y1 = Math.ceil((EXTENDS_3857 - yMax) / tile_size) - 1;//起始y
   let   y2 = Math.ceil((EXTENDS_3857 - yMin) / tile_size) - 1;//终止y

  //防止计算产生负值
  if (x1 < 0) {
    x1 = 0;
  }
  if (x2 < 0) {
    x2 = 0;
  }
  if (y1 < 0) {
    y1 = 0;
  }
  if (y2 < 0) {
    y2 = 0;
  }
  for (let j = x1; j <= x2; j++) {
    for (let k = y1; k <= y2; k++) {
      await tranlaste([j,k,level])
      //j就是url中的x,
      //k就是url中的y,
      //level就是地图等级对应url中的z
    }
  }
}

async function tranlaste(coordinate) {
    await downWithFail(coordinate).then().catch(coordinate=>{
      console.log( coordinate[2] + "/" + coordinate[0], coordinate[1] + ".png下载失败")
    });
}

 function downWithFail(coordinate) {
   return new Promise((resolve, reject) =>{
     let url = getCurrentUrl(mapUrl1, coordinate[0], coordinate[1], coordinate[2]);
     downFile(url, rootPath  + coordinate[2] + "/" + coordinate[0], coordinate[1] + ".png",addModel, function (state1) {
       if(state1!=0){
         url = getCurrentUrl(mapUrl2, coordinate[0], coordinate[1], coordinate[2]);
         downFile(url, rootPath  + coordinate[2] + "/" + coordinate[0], coordinate[1] + ".png",addModel, function (state2) {
           if(state2!=0){
             url = getCurrentUrl(mapUrl3, coordinate[0], coordinate[1], coordinate[2]);
             downFile(url, rootPath + coordinate[2] + "/" + coordinate[0], coordinate[1] + ".png",addModel, function (state3) {
               if(state3!=0){
                 console.log("下载失败");
                 reject(coordinate)
               }else {
                 resolve()
               }
             })
           }else {
             resolve()
           }
         })
       }else {
         resolve()
       }
     })
   });

}

/**
 * 通过proj4js库将4326坐标系转到web墨卡托3857坐标系
 * @param lat
 * @param lng
 * @return {*}
 * @constructor
 */
function Wgs84ToMector2(lat, lng) {
  let x=lat;
  let y=lng;
  return proj4(proj4('EPSG:4326'), proj4('EPSG:3857'), [y, x])
}

function Wgs84ToMector(lat, lng) {
  const EXTENDS_3857 = 20037508.3427892;
  const radio = EXTENDS_3857 / 180;
  let x = lng * radio;
  let y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / Math.PI * 180;
  y = y * radio;
  return [x, y];
}